﻿using Abp.Dependency;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using GN.Pay.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;

namespace GN.Pay.GatewayWeb.Controllers.PayRoute
{
    /// <summary>
    /// 支付特性安装
    /// </summary>
    public class PayRouteInstaller
    {
        private static PayRouteInstaller instance = new PayRouteInstaller();

        /// <summary>
        /// 获取实例
        /// </summary>
        public static PayRouteInstaller Instance
        {
            get
            {
                return PayRouteInstaller.instance;
            }
        }

        private readonly Dictionary<string, Type> routeTypes;

        /// <summary>
        /// 
        /// </summary>
        private PayRouteInstaller()
        {
            this.routeTypes = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
        }

        /// <summary>
        /// 获取是否注册路没
        /// </summary>
        /// <param name="channelId">通道Id</param>
        /// <returns></returns>
        public bool IsRegisterRoute(string channelId)
        {
            if (channelId == null)
            {
                throw new ArgumentNullException(nameof(channelId));
            }
            return routeTypes.ContainsKey(channelId);
        }

        /// <summary>
        /// 支付通道
        /// </summary>
        /// <param name="iocManager">容器</param>
        /// <param name="channelId">通道</param>
        /// <returns></returns>
        public IPayActionRoute Resolve(IIocManager iocManager, string channelId)
        {
            if (IsRegisterRoute(channelId))
            {
                return iocManager.IocContainer.Resolve<IPayActionRoute>(channelId.ToLowerInvariant());
            }
            else
            {
                throw new Abp.UI.UserFriendlyException("不支持支付通道:" + channelId);
            }
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="container"></param>
        /// <param name="IConfigurationStore"></param>
        public void Register(IWindsorContainer container, IConfigurationStore store)
        {
            Assembly assembly = this.GetType().Assembly;
            lock (this)
            {
                if (container == null)
                {
                    throw new ArgumentNullException(nameof(container));
                }
                var dic = TypeUtils.GetAssignableTypeDictionary<IPayActionRoute, PayRouteAttribute>
                    (assembly, t => !t.IsAbstract && !t.IsInterface, true);
                List<IRegistration> routes = new List<IRegistration>();
                foreach (var t in dic)
                {
                    if (!string.IsNullOrWhiteSpace(t.Value.ChannelId))
                    {
                        routes.Add(Component.For<IPayActionRoute>().ImplementedBy(t.Key).Named(t.Value.ChannelId.ToLowerInvariant()));
                        routeTypes[t.Value.ChannelId] = t.Key;
                    }
                }
                if (routes.Count > 0)
                {
                    container.Register(routes.ToArray());
                }
            }
        }
    }
}